Skip to content

Commit 80c77db

Browse files
authored
[lldb] Try Clang fallback in TSSwiftTypeRef::GetNumFields (#6671)
For Clang types, avoid loading Swift ASTContexts in `TypeSystemSwiftTypeRef::GetNumFields`. This new logic checks if a type is an imported Clang type. If it's imported, but no type info is available (ex private/internal types), then zero is returned. If a Clang type is available, then, depending on the type class, return the Clang type's `GetNumFields`. Note that there's logic to avoid calling `GetNumFields` on ObjC types. This is to match the current behavior.
1 parent 2b708dd commit 80c77db

File tree

2 files changed

+50
-25
lines changed

2 files changed

+50
-25
lines changed

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

Lines changed: 48 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2798,27 +2798,48 @@ uint32_t TypeSystemSwiftTypeRef::GetNumFields(opaque_compiler_type_t type,
27982798
ExecutionContext *exe_ctx) {
27992799
LLDB_SCOPED_TIMER();
28002800
FALLBACK(GetNumFields, (ReconstructType(type), exe_ctx));
2801-
if (exe_ctx)
2802-
if (auto *runtime = SwiftLanguageRuntime::Get(exe_ctx->GetProcessSP()))
2803-
if (auto num_fields =
2804-
runtime->GetNumFields(GetCanonicalType(type), exe_ctx))
2805-
// Use a lambda to intercept & unwrap the `Optional` return value from
2806-
// `SwiftLanguageRuntime::GetNumFields`.
2807-
// Optional<uint32_t> uses more lax equivalency function.
2808-
return [&]() -> llvm::Optional<uint32_t> {
2809-
auto impl = [&]() -> llvm::Optional<uint32_t> {
2810-
if (!type)
2811-
return 0;
2812-
return num_fields;
2813-
};
2814-
ExecutionContext exe_ctx_obj;
2815-
if (exe_ctx)
2816-
exe_ctx_obj = *exe_ctx;
2817-
VALIDATE_AND_RETURN(impl, GetNumFields, type, exe_ctx_obj,
2818-
(ReconstructType(type), exe_ctx),
2819-
(ReconstructType(type), exe_ctx));
2820-
}()
2821-
.getValueOr(0);
2801+
2802+
auto impl = [&]() -> llvm::Optional<uint32_t> {
2803+
if (exe_ctx)
2804+
if (auto *runtime = SwiftLanguageRuntime::Get(exe_ctx->GetProcessSP()))
2805+
if (auto num_fields =
2806+
runtime->GetNumFields(GetCanonicalType(type), exe_ctx))
2807+
return num_fields;
2808+
2809+
bool is_imported = false;
2810+
if (auto clang_type = GetAsClangTypeOrNull(type, &is_imported)) {
2811+
switch (clang_type.GetTypeClass()) {
2812+
case lldb::eTypeClassObjCObject:
2813+
case lldb::eTypeClassObjCInterface:
2814+
// Imported ObjC types are treated as having no fields.
2815+
return 0;
2816+
default:
2817+
return clang_type.GetNumFields(exe_ctx);
2818+
}
2819+
} else if (is_imported) {
2820+
// A known imported type, but where clang has no info. Return early to
2821+
// avoid loading Swift ASTContexts, only to return the same zero value.
2822+
LLDB_LOGF(GetLog(LLDBLog::Types),
2823+
"No CompilerType for imported Clang type %s",
2824+
AsMangledName(type));
2825+
return 0;
2826+
}
2827+
return {};
2828+
};
2829+
if (auto num_fields = impl()) {
2830+
// Use a lambda to intercept and unwrap the `Optional` return value.
2831+
// Optional<uint32_t> uses more lax equivalency function.
2832+
return [&]() -> llvm::Optional<uint32_t> {
2833+
auto impl = [&]() { return num_fields; };
2834+
ExecutionContext exe_ctx_obj;
2835+
if (exe_ctx)
2836+
exe_ctx_obj = *exe_ctx;
2837+
VALIDATE_AND_RETURN(impl, GetNumFields, type, exe_ctx_obj,
2838+
(ReconstructType(type), exe_ctx),
2839+
(ReconstructType(type), exe_ctx));
2840+
}()
2841+
.getValueOr(0);
2842+
}
28222843

28232844
LLDB_LOGF(GetLog(LLDBLog::Types),
28242845
"Using SwiftASTContext::GetNumFields fallback for type %s",
@@ -3257,8 +3278,9 @@ bool TypeSystemSwiftTypeRef::IsMeaninglessWithoutDynamicResolution(
32573278
(ReconstructType(type)));
32583279
}
32593280

3260-
CompilerType TypeSystemSwiftTypeRef::GetAsClangTypeOrNull(
3261-
lldb::opaque_compiler_type_t type) {
3281+
CompilerType
3282+
TypeSystemSwiftTypeRef::GetAsClangTypeOrNull(lldb::opaque_compiler_type_t type,
3283+
bool *is_imported) {
32623284
using namespace swift::Demangle;
32633285
Demangler dem;
32643286
NodePointer node = GetDemangledType(dem, AsMangledName(type));
@@ -3275,7 +3297,9 @@ CompilerType TypeSystemSwiftTypeRef::GetAsClangTypeOrNull(
32753297
return node_clangtype.second;
32763298
}
32773299
CompilerType clang_type;
3278-
IsImportedType(type, &clang_type);
3300+
bool imported = IsImportedType(type, &clang_type);
3301+
if (is_imported)
3302+
*is_imported = imported;
32793303
return clang_type;
32803304
}
32813305

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,8 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift {
265265
CompilerType *original_type) override;
266266
/// Like \p IsImportedType(), but even returns Clang types that are also Swift
267267
/// builtins (int <-> Swift.Int) as Clang types.
268-
CompilerType GetAsClangTypeOrNull(lldb::opaque_compiler_type_t type);
268+
CompilerType GetAsClangTypeOrNull(lldb::opaque_compiler_type_t type,
269+
bool *is_imported = nullptr);
269270
CompilerType GetErrorType() override;
270271
CompilerType GetReferentType(lldb::opaque_compiler_type_t type) override;
271272
CompilerType GetInstanceType(lldb::opaque_compiler_type_t type) override;

0 commit comments

Comments
 (0)