Skip to content
Open
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
30 changes: 26 additions & 4 deletions lldb/source/Plugins/Language/Swift/FoundationValueTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,17 +341,39 @@ bool lldb_private::formatters::swift::Data_SummaryProvider(
// where the byte count is the size of _slice. Detect that layout and handle
// it before falling through to the legacy enum logic below.
{
CompilerType repr_type = representation_enum_sp->GetCompilerType();
const uint32_t repr_flags = repr_type.GetTypeInfo();
const bool is_struct = (repr_flags & lldb::eTypeIsStructUnion) &&
!(repr_flags & lldb::eTypeIsEnumeration);

static constexpr llvm::StringLiteral g__storage("_storage");
static constexpr llvm::StringLiteral g__slice("_slice");
ValueObjectSP storage_sp =
representation_enum_sp->GetChildAtNamePath({g__storage});
ValueObjectSP slice_sp =
representation_enum_sp->GetChildAtNamePath({g__slice});
if (slice_sp) {
// Swift's Int is pointer-sized, so a Range<Int> is two pointers wide.
ProcessSP process_sp(valobj.GetProcessSP());
const uint64_t int_size = process_sp ? process_sp->GetAddressByteSize() : 0;
const uint64_t range_size = 2 * int_size;
if (!int_size)
return false;
const uint64_t slice_size =
slice_sp ? llvm::expectedToStdOptional(slice_sp->GetByteSize())
.value_or(0)
: 0;

// Identify the layout structurally: a struct (not the legacy enum) with
// both _storage and a _slice that is exactly two Ints wide.
if (is_struct && storage_sp && slice_sp && slice_size == range_size) {
DataExtractor extractor;
Status error;
if (slice_sp->GetData(extractor, error) < 16 || error.Fail())
if (slice_sp->GetData(extractor, error) < range_size || error.Fail())
return false;
lldb::offset_t offset = 0;
int64_t lowerBound = (int64_t)extractor.GetU64(&offset);
int64_t upperBound = (int64_t)extractor.GetU64(&offset);
// GetAddress() reads a pointer-sized value.
int64_t lowerBound = (int64_t)extractor.GetAddress(&offset);
int64_t upperBound = (int64_t)extractor.GetAddress(&offset);

int64_t count = upperBound - lowerBound;
if (count == 1)
Expand Down
8 changes: 4 additions & 4 deletions lldb/test/API/lang/swift/array_tuple_resilient/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import Foundation
var patatino : [(Data, Int64)] = [(Data([1, 2, 3]), 1001)]
var tinky : [(Data, Data)] = [(Data([1, 2, 3]), Data([9]))]
print(patatino) //%self.expect('frame variable -d run -- patatino',
//% substrs=['byte', '1 = 1001'])
//% substrs=['0 = 3 bytes', '1 = 1001'])
//%self.expect('expr -d run -- patatino',
//% substrs=['byte', '1 = 1001'])
//% substrs=['0 = 3 bytes', '1 = 1001'])

print(tinky) //%self.expect('frame variable -d run -- tinky',
//% substrs=['byte'])
//% substrs=['0 = 3 bytes', '1 = 1 byte'])
//%self.expect('expr -d run -- tinky',
//% substrs=['byte'])
//% substrs=['0 = 3 bytes', '1 = 1 byte'])
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ class TestSwiftExplicitModules(lldbtest.TestBase):
@skipEmbeddedSwift
@swiftTest
@skipUnlessDarwin
# Not working correctly with DWARFImporter. NSData may get an
# incomplete definition that also isn't updated when Foundation is
# imported.
@skipIf(setting=("symbols.use-swift-clangimporter", "false"),
bugnumber="rdar://118337109")
def test_import(self):
"""Test an implicit import inside an explicit build"""
mod_cache = self.getBuildArtifact("my-clang-modules-cache")
Expand All @@ -27,4 +32,4 @@ def test_import(self):
error=True)
self.expect("expression import Foundation")
self.expect('expression Data([1, 2, 3])',
substrs=["byte"])
substrs=["3 bytes"])
4 changes: 2 additions & 2 deletions lldb/test/Shell/SwiftREPL/ResilientArray.test
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ import Foundation

let x : [Data] = [Data([1, 2, 3]), Data([9])]
// CHECK: {{x}}: [Foundation.Data] = 2 values {
// CHECK-NEXT: byte
// CHECK-NEXT: byte
// CHECK-NEXT: [0] = 3 bytes
// CHECK-NEXT: [1] = 1 byte
// CHECK-NEXT: }
8 changes: 4 additions & 4 deletions lldb/test/Shell/SwiftREPL/ResilientDict.test
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ import Foundation
let x : [Data:Int] = [Data([1, 2, 3]): 40, Data([9]): 230]
// DICT-LABEL: {{x}}: [Foundation.Data : Int] = 2 key/value pairs {
// DICT: [{{[0-1]}}] = {
// DICT: byte
// DICT: value = 40
// DICT: key = 3 bytes
// DICT-NEXT: value = 40
// DICT-NEXT: }

let y : [Data:Int] = [Data([1, 2, 3]): 40, Data([9]): 230]
// DICT-LABEL: {{y}}: [Foundation.Data : Int] = 2 key/value pairs {
// DICT: [{{[0-1]}}] = {
// DICT: byte
// DICT: value = 230
// DICT: key = 1 byte
// DICT-NEXT: value = 230
// DICT-NEXT: }