Skip to content

Commit 181173c

Browse files
Merge pull request #472 from adrian-prantl/unions
Add support for C unions in Swift.
2 parents 006b86d + ca7ab28 commit 181173c

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)