Skip to content

[lldb] Add enum support to TypeSystemSwiftTypeRef::DumpTypeValue #2330

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
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
6 changes: 6 additions & 0 deletions lldb/include/lldb/Target/SwiftLanguageRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,12 @@ class SwiftLanguageRuntime : public LanguageRuntime {
llvm::Optional<unsigned> GetNumChildren(CompilerType type,
ValueObject *valobj);

/// Determine the enum case name for the \p data value of the enum \p type.
/// This is performed using Swift reflection.
llvm::Optional<std::string> GetEnumCaseName(CompilerType type,
const DataExtractor &data,
ExecutionContext *exe_ctx);

llvm::Optional<size_t> GetIndexOfChildMemberWithName(
CompilerType type, llvm::StringRef name, ExecutionContext *exe_ctx,
bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes);
Expand Down
129 changes: 85 additions & 44 deletions lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1422,7 +1422,26 @@ static bool ContainsSugaredParen(swift::Demangle::NodePointer node) {

return false;
}


swift::Demangle::NodePointer
StripPrivateIDs(swift::Demangle::Demangler &dem,
swift::Demangle::NodePointer node) {
using namespace swift::Demangle;
return TypeSystemSwiftTypeRef::Transform(dem, node, [&](NodePointer node) {
if (node->getKind() != Node::Kind::PrivateDeclName ||
node->getNumChildren() != 2)
return node;

assert(node->getFirstChild()->getKind() == Node::Kind::Identifier);
assert(node->getLastChild()->getKind() == Node::Kind::Identifier);
auto *new_node = dem.createNode(Node::Kind::PrivateDeclName);
auto *ident = dem.createNodeWithAllocatedText(
Node::Kind::Identifier, node->getLastChild()->getText());
new_node->addChild(ident, dem);
return new_node;
Comment on lines +1427 to +1441
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function strips the private discriminators (identifiers) from a demangled symbol. This function is used when comparing symbols in Equivalent, so that two symbols that differ only by the unique identifier in PrivateDeclName, are considered equal.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this hide bugs where we accidentally mix up these two types named Foo?

a.swift
fileprivate struct Foo {}
b.swift
fileprivate struct Foo { let i = "i am different" }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I want to say is: we need to make sure to not forget to investigate why private discriminators reported by remote mirrors look different than the ones the Swift compiler emits in the debug info.
But that's not something blocking this patch. (But maybe there should be a bug FIXME in the code).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch. I'll have to constrain this more.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up asking about this, and the explanation is:

the private identifier is not ABI and doesn't show up in any runtime data structures. the $ is the address of the anonymized context descriptor that represents the private scope. there are no stable string identifiers for private or local types

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the purpose of verification, it's okay to compare tham in a relaxed manner. But for correctness, this is a potential problem with our incremental adoption of TypeSystemSwiftTypeRef. Since we mix&match between type systems, this makes it impossible to convert between AST <-> TypeRef types with private discriminators unless we have a ValueObject with an AST type to bind the two together.

We do store the private discriminator of each source file in DWARF (as a DW_TAG_namespace). If there is a way to tie a typeref type to a DWARF compile unit, we could do the conversion from runtime -> ast discriminator. But I don't think this is going to be possible in all cases: For example when using remote mirrors to resolve the dynamic type of an existential, how would we know where that type was defined?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is my understanding here correct?

This is a problem for private types which lldb has the AST for. For the SDK, we'll never have private types, so the issue of AST <-> TypeRef conversion can't occur for SDK types.

For project code, there is code that's built using full swiftmodules, and code that's builds using library evolution and swiftinterfaces. For builds using full fidelity swiftmodules, can or should lldb use the AST only? If AST were strictly used when it's available, and TypeRefs used only when the AST is not available, then would we never need to worry about conversion? However, would we be able to recognize the difference between a full swiftmodule, and a swiftmodule generated from a swiftinterface?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure whether the TypeRef can be cross referenced to a compile unit. I'll have to look into that.

I wonder if we can cross reference through uniqueness? If, ignoring the private identifier, there's only a single type by that name (unlike say your fileprivate struct Foo example), then if we enumerated all types we would see that there's just the one. However that sounds heavy handed and poor for performance/maintenance.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we mix&match between type systems

do we need to do this, and if so why? To put it another way, if we get a private TypeRef, when might lldb try to use that type in an AST context, vs always using reflection for such types? In other words, once you go TypeRef, do you ever need to go back to AST?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is my understanding here correct?

This is a problem for private types which lldb has the AST for. For the SDK, we'll never have private types, so the issue of AST <-> TypeRef conversion can't occur for SDK types.

No Swift ASTs are shipped for the SDK overlays. Therefore, we may get private types from Remote Mirrors, but never in the ASTs. This same is not true for development builds where we build the older snapshot of the Swift overlays that is inside the apple/swift repository from source.

The situation for SDK types could arise in the testsuite but not in production.

For project code, there is code that's built using full swiftmodules, and code that's builds using library evolution and swiftinterfaces. For builds using full fidelity swiftmodules, can or should lldb use the AST only? If AST were strictly used when it's available, and TypeRefs used only when the AST is not available, then would we never need to worry about conversion? However, would we be able to recognize the difference between a full swiftmodule, and a swiftmodule generated from a swiftinterface?

Here is gets much more complicated. In the expression evaluator all type lookup requests from the Swift compiler get sent back to LLDB, and it's LLDB's job to resolve type names. LLDB might perform dynamic type resolution (using Remote Mirrors) here and then could try to reconstruct a type that does not exist in the AST world. We also can run into the exact same issue with Clang types. Dynamic type resolution can return a private implementation subclass (e.g., NSString has multiple internal implementations) that the AST cannot know about because its declaration is not part of the SDK at all.
In the case of private subclasses, we could try reconstructing more general types (superclasses) until we find one that can be reconstructed. But this does not work for all private types in general. LLDB would probably need to make up a declaration for these types and hand it to the AST.

});
}

/// Compare two swift types from different type systems by comparing their
/// (canonicalized) mangled name.
template <> bool Equivalent<CompilerType>(CompilerType l, CompilerType r) {
Expand All @@ -1443,10 +1462,10 @@ template <> bool Equivalent<CompilerType>(CompilerType l, CompilerType r) {
if (ContainsUnresolvedTypeAlias(r_node) ||
ContainsGenericTypeParameter(r_node) || ContainsSugaredParen(r_node))
return true;
if (swift::Demangle::mangleNode(
TypeSystemSwiftTypeRef::CanonicalizeSugar(dem, l_node)) ==
swift::Demangle::mangleNode(
TypeSystemSwiftTypeRef::CanonicalizeSugar(dem, r_node)))
if (swift::Demangle::mangleNode(StripPrivateIDs(
dem, TypeSystemSwiftTypeRef::CanonicalizeSugar(dem, l_node))) ==
swift::Demangle::mangleNode(StripPrivateIDs(
dem, TypeSystemSwiftTypeRef::CanonicalizeSugar(dem, r_node))))
return true;

// SwiftASTContext hardcodes some less-precise types.
Expand Down Expand Up @@ -2296,6 +2315,8 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex(
child_bitfield_bit_offset, child_is_base_class,
child_is_deref_of_parent, valobj, language_flags);
};
auto ast_num_children = m_swift_ast_context->GetNumChildren(
ReconstructType(type), omit_empty_base_classes, exe_ctx);
auto impl = [&]() -> CompilerType {
ExecutionContextScope *exe_scope = nullptr;
if (exe_ctx)
Expand All @@ -2315,9 +2336,15 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex(
if (llvm::StringRef(AsMangledName(type))
.endswith("sSo18NSNotificationNameaD"))
return GetTypeFromMangledTypename(ConstString("$sSo8NSStringCD"));
// FIXME: Private discriminators come out in a different format.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How was this resolved in this patch?

Copy link
Author

@kastiglione kastiglione Jan 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not entirely resolved, more changes required, one at least is to support validation. But it's removal is required to support Foundation.IndexPath.Storage whose type would be ignored by this condition.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See here: #2330 (comment)

if (result.GetMangledTypeName().GetStringRef().count('$') > 1)
return fallback();
Comment on lines -2319 to -2320
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's a thought. In this case, we could have two levels of "fallback" logic:

if TypeRef type contains '$'
    if AST has type
        return AST type
    else
        return TypeRef type

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've had some second thoughts about this fallback logic. A possible deal breaker is that the AST could contain fewer children, and that would make the index invalid. In other words, a runtime index could return some other child in the AST. To proceed, we'd have to compare the AST child to see that it matches the runtime child, modulo the private identifier, but that style of comparison is in-exact which could cause rare bugs.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we add a if GetNumChildren(typeref) == GetNumChildren(ast) condition to the fallback and error out otherwise?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the fallback with a child count check in 3dad37a.

if (result.GetMangledTypeName().GetStringRef().count('$') > 1 &&
ast_num_children == runtime->GetNumChildren({this, type}, valobj))
// If available, prefer the AST for private types. Private
// identifiers are not ABI; the runtime returns anonymous private
// identifiers (using a '$' prefix) which cannot match identifiers
// in the AST. Because these private types can't be used in an AST
// context, prefer the AST type if available.
if (auto ast_type = fallback())
return ast_type;
return result;
}
}
Expand Down Expand Up @@ -2416,8 +2443,7 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex(
// Because the API deals out an index into a list of children we
// can't mix&match between the two typesystems if there is such a
// divergence. We'll need to replace all calls at once.
if (m_swift_ast_context->GetNumChildren(ReconstructType(type),
omit_empty_base_classes, exe_ctx) <
if (ast_num_children <
runtime->GetNumChildren({this, type}, valobj).getValueOr(0))
return impl();

Expand All @@ -2436,9 +2462,9 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex(
ast_child_name = suffix.str();
assert((llvm::StringRef(child_name).contains('.') ||
Equivalent(child_name, ast_child_name)));
assert((Equivalent(llvm::Optional<uint64_t>(child_byte_size),
llvm::Optional<uint64_t>(ast_child_byte_size)) ||
ast_language_flags));
assert(ast_language_flags ||
(Equivalent(llvm::Optional<uint64_t>(child_byte_size),
llvm::Optional<uint64_t>(ast_child_byte_size))));
assert(Equivalent(llvm::Optional<uint64_t>(child_byte_offset),
llvm::Optional<uint64_t>(ast_child_byte_offset)));
assert(
Expand Down Expand Up @@ -2778,37 +2804,14 @@ bool TypeSystemSwiftTypeRef::DumpTypeValue(
size_t data_byte_size, uint32_t bitfield_bit_size,
uint32_t bitfield_bit_offset, ExecutionContextScope *exe_scope,
bool is_base_class) {
if (!type)
return false;

using namespace swift::Demangle;
Demangler dem;
auto *node = DemangleCanonicalType(dem, type);
auto kind = node->getKind();

switch (kind) {
case Node::Kind::Structure: {
// TODO: Handle ObjC enums masquerading as structs.
// In rare instances, a Swift `Structure` wraps an ObjC enum. An example is
// `$sSo16ComparisonResultVD`. For now, use `SwiftASTContext` to handle
// these enum structs.
auto resolved = ResolveTypeAlias(m_swift_ast_context, dem, node, true);
auto clang_type = std::get<CompilerType>(resolved);
bool is_signed;
if (!clang_type.IsEnumerationType(is_signed))
break;
LLVM_FALLTHROUGH;
}
case Node::Kind::Enum:
case Node::Kind::BoundGenericEnum:
// TODO: Add support for Enums.
return m_swift_ast_context->DumpTypeValue(
ReconstructType(type), s, format, data, data_offset, data_byte_size,
bitfield_bit_size, bitfield_bit_offset, exe_scope, is_base_class);
}

auto impl = [&]() -> bool {
switch (kind) {
if (!type)
return false;

using namespace swift::Demangle;
Demangler dem;
auto *node = DemangleCanonicalType(dem, type);
switch (node->getKind()) {
case Node::Kind::Class:
case Node::Kind::BoundGenericClass:
if (is_base_class)
Expand Down Expand Up @@ -2868,9 +2871,47 @@ bool TypeSystemSwiftTypeRef::DumpTypeValue(
s, format, data, data_offset, data_byte_size, bitfield_bit_size,
bitfield_bit_offset, exe_scope, is_base_class);
}
case Node::Kind::Structure:
case Node::Kind::BoundGenericStructure:
return false;
case Node::Kind::Structure: {
// In some instances, a swift `structure` wraps an objc enum. The enum

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we know what "some instances" are?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are many instances. I'm not currently sure which objc enums are mangled as structs, and which aren't, nor why. It's something I could look into.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's save that investigation for another day.

// case needs to be handled, but structs are no-ops.
auto resolved = ResolveTypeAlias(m_swift_ast_context, dem, node, true);
auto clang_type = std::get<CompilerType>(resolved);
if (!clang_type)
return false;

bool is_signed;
if (!clang_type.IsEnumerationType(is_signed))
// The type is a clang struct, not an enum.
return false;

// The type is an enum imported from clang. Try Swift type metadata first,
// and failing that fallback to the AST.
LLVM_FALLTHROUGH;
}
case Node::Kind::Enum:
case Node::Kind::BoundGenericEnum: {
if (exe_scope)
if (auto runtime =
SwiftLanguageRuntime::Get(exe_scope->CalculateProcess())) {
ExecutionContext exe_ctx;
exe_scope->CalculateExecutionContext(exe_ctx);
if (auto case_name =
runtime->GetEnumCaseName({this, type}, data, &exe_ctx)) {
s->PutCString(*case_name);
return true;
}
}

// No result available from the runtime, fallback to the AST.
// This can happen in two cases:
// 1. MultiPayloadEnums not currently supported by Swift reflection
// 2. Some clang imported enums
return m_swift_ast_context->DumpTypeValue(
ReconstructType(type), s, format, data, data_offset, data_byte_size,
bitfield_bit_size, bitfield_bit_offset, exe_scope, is_base_class);
}
default:
assert(false && "Unhandled node kind");
LLDB_LOGF(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES),
Expand Down
12 changes: 12 additions & 0 deletions lldb/source/Target/SwiftLanguageRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,13 @@ class SwiftLanguageRuntimeStub {
return {};
}

llvm::Optional<std::string> GetEnumCaseName(CompilerType type,
const DataExtractor &data,
ExecutionContext *exe_ctx) {
STUB_LOG();
return {};
}

llvm::Optional<size_t> GetIndexOfChildMemberWithName(
CompilerType type, llvm::StringRef name, ExecutionContext *exe_ctx,
bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) {
Expand Down Expand Up @@ -2168,6 +2175,11 @@ SwiftLanguageRuntime::GetNumChildren(CompilerType type, ValueObject *valobj) {
FORWARD(GetNumChildren, type, valobj);
}

llvm::Optional<std::string> SwiftLanguageRuntime::GetEnumCaseName(
CompilerType type, const DataExtractor &data, ExecutionContext *exe_ctx) {
FORWARD(GetEnumCaseName, type, data, exe_ctx);
}

llvm::Optional<size_t> SwiftLanguageRuntime::GetIndexOfChildMemberWithName(
CompilerType type, llvm::StringRef name, ExecutionContext *exe_ctx,
bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) {
Expand Down
58 changes: 53 additions & 5 deletions lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ class LLDBMemoryReader : public swift::remote::MemoryReader {
} else {
*result = 0;
}
break;
return true;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Swift reflection code expects this function to return true when a valid value is assigned to outBuffer.

}
case DLQ_GetPointerSize: {
auto result = static_cast<uint8_t *>(outBuffer);
Expand All @@ -304,6 +304,15 @@ class LLDBMemoryReader : public swift::remote::MemoryReader {
*result = m_process.GetAddressByteSize(); // FIXME: sizeof(size_t)
return true;
}
case DLQ_GetLeastValidPointerValue: {
auto *result = (uint64_t *)outBuffer;
auto &triple = m_process.GetTarget().GetArchitecture().GetTriple();
if (triple.isOSDarwin() && triple.isArch64Bit())
*result = 0x100000000;
else
*result = 0x1000;
return true;
Comment on lines +307 to +314
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was previously unimplemented, and so would return false for DLQ_GetLeastValidPointerValue queries. This caused projectEnumValue in Swift reflection to fail.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See also rdar://70729149

}
}

return false;
Expand Down Expand Up @@ -381,8 +390,8 @@ class LLDBMemoryReader : public swift::remote::MemoryReader {
uint64_t size) override {
if (m_local_buffer) {
auto addr = address.getAddressData();
if (addr >= m_local_buffer &&
addr + size <= m_local_buffer + m_local_buffer_size) {
if (addr >= *m_local_buffer &&
addr + size <= *m_local_buffer + m_local_buffer_size) {
// If this crashes, the assumptions stated in
// GetDynamicTypeAndAddress_Protocol() most likely no longer
// hold.
Expand Down Expand Up @@ -472,15 +481,15 @@ class LLDBMemoryReader : public swift::remote::MemoryReader {

void popLocalBuffer() {
lldbassert(m_local_buffer);
m_local_buffer = 0;
m_local_buffer.reset();
m_local_buffer_size = 0;
}

private:
Process &m_process;
size_t m_max_read_amount;

uint64_t m_local_buffer = 0;
llvm::Optional<uint64_t> m_local_buffer;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some enum values are zero sized. Because of the asserts in this function, PushLocalBuffer() previously should be only called if the buffer was non-zero. This means you'd have to write code like:

if (buffer)
  pushLocalBuffer(...);
DO STUFF
if (buffer)
  popLocalBuffer();

By using optional, the calling code can be made unconditional:

pushLocalBuffer(...);
DO STUFF
popLocalBuffer();

This works better with make_scope_exit too.

uint64_t m_local_buffer_size = 0;
};

Expand Down Expand Up @@ -1219,6 +1228,45 @@ findFieldWithName(const std::vector<swift::reflection::FieldInfo> &fields,
return child_indexes.size();
}

static llvm::Optional<std::string>
GetMultiPayloadEnumCaseName(const swift::reflection::EnumTypeInfo *eti,
const DataExtractor &data) {
assert(eti->getEnumKind() == swift::reflection::EnumKind::MultiPayloadEnum);
auto payload_capacity = eti->getPayloadSize();
if (data.GetByteSize() == payload_capacity + 1) {
auto tag = data.GetDataStart()[payload_capacity];
const auto &cases = eti->getCases();
if (tag >= 0 && tag < cases.size())
return cases[tag].Name;
}
return {};
}

llvm::Optional<std::string> SwiftLanguageRuntimeImpl::GetEnumCaseName(
CompilerType type, const DataExtractor &data, ExecutionContext *exe_ctx) {
using namespace swift::reflection;
using namespace swift::remote;
auto *ti = GetTypeInfo(type, exe_ctx->GetFramePtr());
if (ti->getKind() != TypeInfoKind::Enum)
return {};

auto *eti = llvm::cast<EnumTypeInfo>(ti);
PushLocalBuffer((int64_t)data.GetDataStart(), data.GetByteSize());
auto defer = llvm::make_scope_exit([&] { PopLocalBuffer(); });
RemoteAddress addr(data.GetDataStart());
int case_index;
if (eti->projectEnumValue(*GetMemoryReader(), addr, &case_index))
return eti->getCases()[case_index].Name;

// Temporary workaround.
if (eti->getEnumKind() == EnumKind::MultiPayloadEnum &&
type.GetMangledTypeName().GetStringRef().startswith(
"$s10Foundation9IndexPathV7Storage10"))
return GetMultiPayloadEnumCaseName(eti, data);
Comment on lines +1261 to +1265
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The work around is currently limited to Foundation.IndexPath.Storage, because that's the only case surfaced by the lldb test suite. I'd like this to be exhaustive, but I'll have to do some work to identify other any other multipayload enums in Foundation that we need to test and hardcode a special case for.


return {};
}

llvm::Optional<size_t> SwiftLanguageRuntimeImpl::GetIndexOfChildMemberWithName(
CompilerType type, llvm::StringRef name, ExecutionContext *exe_ctx,
bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) {
Expand Down
4 changes: 4 additions & 0 deletions lldb/source/Target/SwiftLanguageRuntimeImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ class SwiftLanguageRuntimeImpl {
llvm::Optional<unsigned> GetNumFields(CompilerType type,
ExecutionContext *exe_ctx);

llvm::Optional<std::string> GetEnumCaseName(CompilerType type,
const DataExtractor &data,
ExecutionContext *exe_ctx);

llvm::Optional<size_t> GetIndexOfChildMemberWithName(
CompilerType type, llvm::StringRef name, ExecutionContext *exe_ctx,
bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@
from lldbsuite.test.decorators import *

lldbinline.MakeInlineTest(__file__, globals(),
decorators=[swiftTest,skipIf(oslist=['windows'])])
decorators=[swiftTest,skipIf(oslist=['windows', 'linux'])])