Skip to content

Commit ca7ab28

Browse files
committed
Add support for C unions in Swift.
C unions are struct types in Swift, but their fields are not implemented as stored properties, so the default implementation did not work for them. This patch adds special handling for unions by iterating over the imported VarDecls. rdar://problem/55026321
1 parent 3850e3e commit ca7ab28

File tree

6 files changed

+77
-0
lines changed

6 files changed

+77
-0
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
SWIFT_SOURCES := main.swift
2+
SWIFTFLAGS_EXTRAS = -I$(SRCDIR)
3+
4+
include Makefile.rules
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import lldb
2+
from lldbsuite.test.decorators import *
3+
import lldbsuite.test.lldbtest as lldbtest
4+
import lldbsuite.test.lldbutil as lldbutil
5+
import os
6+
import unittest2
7+
8+
9+
class TestSwiftAnyType(lldbtest.TestBase):
10+
11+
mydir = lldbtest.TestBase.compute_mydir(__file__)
12+
13+
@swiftTest
14+
def test_c_unions(self):
15+
self.build()
16+
target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
17+
self, 'break here', lldb.SBFileSpec('main.swift'))
18+
self.expect("target variable -- i", substrs=['42'])
19+
self.expect("target variable -- d", substrs=['23'])
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import U
2+
3+
func use<T>(_ t : T) {}
4+
5+
let i = IntDoubleUnion(i: 42)
6+
let d = IntDoubleUnion(d: 23)
7+
use((i, d)) // break here
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module U { header "union.h" }
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
union IntDoubleUnion {
2+
int i;
3+
double d;
4+
};

lldb/source/Symbol/SwiftASTContext.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6648,6 +6648,16 @@ uint32_t SwiftASTContext::GetNumFields(void *type) {
66486648
case swift::TypeKind::BoundGenericClass:
66496649
case swift::TypeKind::BoundGenericStruct: {
66506650
auto nominal = swift_can_type->getAnyNominal();
6651+
// Imported unions don't have stored properties.
6652+
if (auto *ntd =
6653+
llvm::dyn_cast_or_null<swift::NominalTypeDecl>(nominal->getDecl()))
6654+
if (auto *rd = llvm::dyn_cast_or_null<clang::RecordDecl>(ntd->getClangDecl()))
6655+
if (rd->isUnion()) {
6656+
swift::DeclRange ms = ntd->getMembers();
6657+
return std::count_if(ms.begin(), ms.end(), [](swift::Decl *D) {
6658+
return llvm::isa<swift::VarDecl>(D);
6659+
});
6660+
}
66516661
return GetStoredProperties(nominal).size();
66526662
}
66536663

@@ -7295,6 +7305,38 @@ CompilerType SwiftASTContext::GetChildCompilerTypeAtIndex(
72957305
case swift::TypeKind::Struct:
72967306
case swift::TypeKind::BoundGenericStruct: {
72977307
auto nominal = swift_can_type->getAnyNominal();
7308+
7309+
// Imported unions don't have stored properties, iterate over the
7310+
// VarDecls instead.
7311+
if (auto *ntd =
7312+
llvm::dyn_cast_or_null<swift::NominalTypeDecl>(nominal->getDecl()))
7313+
if (auto *rd = llvm::dyn_cast_or_null<clang::RecordDecl>(ntd->getClangDecl()))
7314+
if (rd->isUnion()) {
7315+
unsigned count = 0;
7316+
for (swift::Decl *D : ntd->getMembers()) {
7317+
auto *VD = llvm::dyn_cast_or_null<swift::VarDecl>(D);
7318+
if (!VD)
7319+
continue;
7320+
if (count++ < idx)
7321+
continue;
7322+
7323+
swift::Type child_swift_type = VD->getType();
7324+
7325+
CompilerType child_type =
7326+
ToCompilerType(VD->getType().getPointer());
7327+
child_name = VD->getNameStr();
7328+
if (!get_type_size(child_byte_size, child_type))
7329+
return {};
7330+
child_is_base_class = false;
7331+
child_is_deref_of_parent = false;
7332+
child_byte_offset = 0;
7333+
child_bitfield_bit_size = 0;
7334+
child_bitfield_bit_offset = 0;
7335+
return child_type;
7336+
}
7337+
return {};
7338+
}
7339+
72987340
auto stored_properties = GetStoredProperties(nominal);
72997341
if (idx >= stored_properties.size())
73007342
break;

0 commit comments

Comments
 (0)